#include "RingQueue.hpp"
#include "Task.hpp"
using namespace std;

struct ThreadData
{
    RingQueue<Task> *rq;
    string name;
};

void *productor(void *args)
{
    ThreadData *td = static_cast<ThreadData *>(args);
    RingQueue<Task> *rq = td->rq;
    while (true)
    {
        int data1 = rand() % 10 + 1;
        usleep(10);
        int data2 = rand() % 10 + 1;
        char op=ops[rand()%ops.size()];
        Task t(data1,data2,op);
        rq->push(t);
        pthread_mutex_lock(&print_mutex);
        cout << td->name << " product data:" << t.getTask() << endl;
        pthread_mutex_unlock(&print_mutex);
        sleep(1);
    }

    return nullptr;
}

void *comsumer(void *args)
{
    ThreadData *td = static_cast<ThreadData *>(args);
    RingQueue<Task> *rq = td->rq;
    while (true)
    {
        Task t;
        rq->pop(&t);
        pthread_mutex_lock(&print_mutex);
        cout << td->name << " get data:" << t.getResult() << endl;
        pthread_mutex_unlock(&print_mutex);
        sleep(1);
    }
    return nullptr;
}

int main()
{
    srand(time(nullptr) ^ getpid());
    RingQueue<Task> *rq = new RingQueue<Task>(50);
    pthread_t c[5], p[3];
    for (int i = 0; i < 3; ++i)
    {
        ThreadData *td=new ThreadData;
        td->rq = rq;
        td->name = "productor-" + to_string(i);
        pthread_create(p + i, nullptr, productor, (void *)td);
    }

    for (int i = 0; i < 5; ++i)
    {
        ThreadData *td=new ThreadData;
        td->rq = rq;
        td->name = "comsumer-" + to_string(i);
        pthread_create(c + i, nullptr, comsumer, (void *)td);
    }

    for (int i = 0; i < 3; ++i)
    {
        pthread_join(p[i], nullptr);
    }

    for (int i = 0; i < 5; ++i)
    {
        pthread_join(c[i], nullptr);
    }

    return 0;
}